package com.resource.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.resource.constant.OfficeApiConstants;
import com.resource.converter.ContractConverter;
import com.resource.converter.ProjectConverter;
import com.resource.dto.*;
import com.resource.query.ProjectQuery;
import com.resource.query.ProjectValidateQuery;
import com.resource.request.ContractSaveRequest;
import com.resource.request.OfficeProjectRequest;
import com.resource.response.ContractDetailResponse;
import com.resource.response.OfficeProjectInfoResponse;
import com.resource.response.OfficeResponse;
import com.resource.service.ContractService;
import com.resource.service.OfficeProjectService;
import com.resource.service.OfficeTokenService;
import com.resource.spring.ApiAssert;
import com.resource.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.*;

/**
 * 项目管理模块
 *
 * @Author: xianggaoxiong
 * @Date: 2020-09-22 18:27
 **/
@Slf4j
@Service
public class OfficeProjectServiceImpl implements OfficeProjectService {
	@Resource
	private RestTemplate restTemplate;
	@Value("${office.app.user}")
	private String user;
	@Value("${office.api.url}")
	private String apiUrl;
	@Resource
	private ProjectConverter projectConverter;
	@Resource
	private ContractService contractService;
	@Resource
	private OfficeTokenService tokenService;
	@Resource
	private ContractConverter contractConverter;

	@Override
	public OfficeProjectInfoDto getProjectInfoById(Integer id) {
		String url = String.format(OfficeApiConstants.PROJECT_INFO_URL, apiUrl) + id;
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.GET, "parameters", user);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity,
				OfficeResponse.class);
		log.info("【office】project detail return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		OfficeResponse officeResponse = ValidateUtils.checkResponse(responseEntity);
		OfficeProjectInfoResponse convert = Convert.convert(OfficeProjectInfoResponse.class, officeResponse.getData());
		return projectConverter.responseToDto(convert);
	}

	@Override
	public List<OfficeProjectInfoDto> getProjectList(ProjectQuery query) {
		String userId = StrUtil.isEmpty(query.getUserId()) ? user : query.getUserId();
		String token = tokenService.getToken(userId);
		String url = String.format(OfficeApiConstants.PROJECT_LIST, apiUrl) + userId + "?manager_type="
				+ query.getManager_type() + "&page=" + query.getPage() + "&limit=" + query.getLimit()
				+ "&list_type=custom" + "&search={search}";
		Map<String, List<String>> condition;
		try {
			condition = SearchUtils.getQuery(query);
		} catch (Exception e) {
			throw new ServiceException("项目获取查询条件失败");
		}
		Map<String, Object> params = new HashMap<>(2);
		params.put("search", JSONUtil.toJsonStr(condition));
		HttpHeaders headers = new HttpHeaders();
		headers.set("Authorization", "Bearer " + token);
		HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity,
				OfficeResponse.class, params);
		log.info("【office】project list return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		OfficeResponse officeResponse = ValidateUtils.checkResponse(responseEntity);
		PageInfo<OfficeProjectInfoResponse> pageInfo = Convert
				.convert(new TypeReference<PageInfo<OfficeProjectInfoResponse>>() {
				}, officeResponse.getData());
		return projectConverter.responseToDto(pageInfo.getList());
	}

	@Override
	public void addProject(OfficeProjectInfoDto dto) {
		String url = String.format(OfficeApiConstants.PROJECT_ADD, apiUrl);
		// 创建请求头
		OfficeProjectRequest officeProject = projectConverter.dtoToRequest(dto);
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.POST, JSONUtil.toJsonStr(officeProject), user);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity,
				OfficeResponse.class);
		log.info("【office】project add return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		ValidateUtils.checkResponse(responseEntity);
	}

	@Override
	public void modifyProject(OfficeProjectInfoDto dto) {
		String url = String.format(OfficeApiConstants.PROJECT_MODIFY, apiUrl) + dto.getManagerId();
		OfficeProjectRequest officeProject = projectConverter.dtoToRequest(dto);
		ApiAssert.isEmpty("项目负责人不能为空", dto.getManagerPerson());
		String[] split = dto.getManagerPerson().split(",");
		// 创建请求头
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.PUT, JSONUtil.toJsonStr(officeProject),
				split[0]);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, entity,
				OfficeResponse.class);
		log.info("【office】project update return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		ValidateUtils.checkResponse(responseEntity);
	}

	@Override
	public void removeProject(Integer managerId) {
		String url = String.format(OfficeApiConstants.PROJECT_REMOVE, apiUrl) + "?fpi=project_delete&manager_id="
				+ managerId;
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.DELETE, OfficeApiConstants.IS_NULL, user);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, entity,
				OfficeResponse.class);
		log.info("【office】project delete return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		ValidateUtils.checkResponse(responseEntity);
	}

	@Override
	public String processFormValidate(ProjectValidateQuery query) {
		Map<String, List<String>> condition;
		try {
			condition = SearchUtils.getQuery(query);
			if (MapUtils.isEmpty(condition)) {
				return OfficeApiConstants.TRUE;
			}
		} catch (Exception e) {
			throw new ServiceException("流程项目校验查询条件失败");
		}
		Map<String, Object> paramsQuery = new HashMap<>(condition);
		paramsQuery.put("__relation__", "or");
		Map<String, Object> multiSearch = new HashMap<>(1);
		multiSearch.put("multiSearch", paramsQuery);
		Map<String, Object> params = new HashMap<>(1);
		params.put("search", JSONUtil.toJsonStr(multiSearch));
		String url = String.format(OfficeApiConstants.PROJECT_LIST, apiUrl) + user + "?search={search}";
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.GET, null, user);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity,
				OfficeResponse.class, params);
		log.info("【office】project process validate list return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		OfficeResponse officeResponse = ValidateUtils.checkResponse(responseEntity);
		PageInfo<OfficeProjectInfoResponse> pageInfo = Convert
				.convert(new TypeReference<PageInfo<OfficeProjectInfoResponse>>() {
				}, officeResponse.getData());
		if (CollUtil.isEmpty(pageInfo.getList())) {
			return OfficeApiConstants.TRUE;
		}
		StringBuilder erroMsg = new StringBuilder();
		pageInfo.getList().forEach(e -> {
			if (e.getManager_name().equals(query.getManager_name())) {
				erroMsg.append("项目名称：【").append(query.getManager_name()).append("】已存在;");
			}
			if (e.getManager_number().equals(query.getManager_number())) {
				erroMsg.append("项目编号：【").append(query.getManager_number()).append("】已存在;");
			}
		});
		return erroMsg.toString();
	}

	@Override
	public String modifyContract(ProjectQuery projectQuery) {
		// 通过项目关联的合同，查询合同信息
		List<OfficeProjectInfoDto> projectList = getProjectListByIdAndName(projectQuery);
		ContractDetailResponse contractDetailResponse = contractService
				.queryContractById(Integer.valueOf(projectList.get(0).getRawRelationContract()));
		// 更新合同信息
		String projectId = contractDetailResponse.getProjectId();
		ContractSaveRequest contractSaveRequest = BeanUtil.copyProperties(contractDetailResponse,
				ContractSaveRequest.class);
		if (StrUtil.isNotEmpty(projectId)) {
			String[] ids = StrUtil.split(projectId, ",");
			ArrayList<String> projectIds = new ArrayList<>(Arrays.asList(ids));
			projectIds.add(String.valueOf(projectList.get(0).getManagerId()));
			contractSaveRequest.setProjectId(projectIds);
		} else {
			ArrayList<String> projectIds = new ArrayList<>();
			projectIds.add(String.valueOf(projectList.get(0).getManagerId()));
			contractSaveRequest.setProjectId(projectIds);
		}
		ContractSaveDto contractSaveDto = new ContractSaveDto();
		ContractSaveMainDto main = contractConverter.requestToAddDto(contractSaveRequest);
		main.setStatus(contractDetailResponse.getStatus());
		contractSaveDto.setContract(main);
		contractSaveDto.setChildContracts(contractDetailResponse.getChildContract());
		contractService.updateContractBySend(contractSaveDto);
		return "操作成功！";
	}

	private List<OfficeProjectInfoDto> getProjectListByIdAndName(ProjectQuery projectQuery) {
		List<OfficeProjectInfoDto> projectList = getProjectList(projectQuery);
		if (CollUtil.isEmpty(projectList)) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			projectList = getProjectList(projectQuery);
		}
		if (CollUtil.isEmpty(projectList)) {
			try {
				Thread.sleep(20000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			projectList = getProjectList(projectQuery);
		}
		if (CollUtil.isEmpty(projectList) || projectList.size() != 1) {
			log.info("【update contract error】{}{}", JSONUtil.toJsonStr(projectQuery), JSONUtil.toJsonStr(projectList));
			throw new ServiceException("参数有误！");
		}
		return projectList;
	}

	@Override
	public void importProject(ProjectImportDto dto) {
		String url = String.format(OfficeApiConstants.PROJECT_ADD, apiUrl);
		// 创建请求头
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.POST, JSONUtil.toJsonStr(dto), user);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity,
				OfficeResponse.class);
		log.info("【office】project import add return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		ValidateUtils.checkResponse(responseEntity);
	}

	@Override
	public void importProjectTask(ProjectTaskImportDto dto,String userId) {
		String url = String.format(OfficeApiConstants.PROJECT_TASK_ADD, apiUrl);
		// 创建请求头
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.POST, JSONUtil.toJsonStr(dto), userId);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity,
				OfficeResponse.class);
		log.info("【office】project task import add return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		ValidateUtils.checkResponse(responseEntity);
	}

	@Override
	public List<JSONObject> exportProject() {
		String token = tokenService.getToken(user);
		String url = String.format(OfficeApiConstants.PROJECT_LIST, apiUrl) + user
				+ "?manager_type=2&page=0&@with_my_project_not_read=0&@with_my_task_count=0&@with_my_question_count=0&@with_my_doc_count=0";
		// 创建请求头
		HttpHeaders headers = new HttpHeaders();
		headers.set("Authorization", "Bearer " + token);
		HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity,
				OfficeResponse.class);
		// 校验返回http请求返回信息
		OfficeResponse officeResponse = ValidateUtils.checkResponse(responseEntity);
		PageInfo<JSONObject> pageInfo = Convert.convert(new TypeReference<PageInfo<JSONObject>>() {
		}, officeResponse.getData());
		return pageInfo.getList();
	}

	@Override
	public void importUpdateProject(ProjectUpdateImportDto dto) {
		String url = String.format(OfficeApiConstants.PROJECT_MODIFY, apiUrl)+dto.getManager_id();
		// 创建请求头
		HttpEntity<String> entity = HttpUtils.setHttpEntity(HttpMethod.PUT, JSONUtil.toJsonStr(dto), user);
		ResponseEntity<OfficeResponse> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, entity,
				OfficeResponse.class);
		log.info("【office】project update add return：{}", JSONUtil.toJsonStr(responseEntity));
		// 校验返回http请求返回信息
		ValidateUtils.checkResponse(responseEntity);
	}
}
